import java.util.LinkedList;
import java.util.ListIterator;


public class Ideal extends Simulation {

	private LinkedList<Node> badNodes = new LinkedList<Node>();

	public Ideal(double bTotal, long tMax, double lambda, double mu, int nodesNum) {
		super(bTotal, tMax, lambda, mu, nodesNum);
	}

	public double makeNodesShift(double maxDistanceToRun) {
		Node lastBad = getLastBadNode();
		if(lastBad == null) {
			//no bad nodes - relIdx-s remain the same
			return maxDistanceToRun;
		} else {
			double srcMovement = Math.min(bTotal - lastBad.relIdx,maxDistanceToRun); 
			
			updateNodesRelIdx(srcMovement, maxDistanceToRun);
			return srcMovement;
		}

	}

	private Node getLastBadNode() {
		double lastIdx = -1;
		Node lastNode =  null;
		for(Node n: badNodes) {
			if(n.relIdx > lastIdx) {
				lastIdx = n.relIdx;
				lastNode = n;
			}
		}
		
		return lastNode;
	}

	protected void addToBadList(Node evNode) {
		badNodes.addLast(evNode);
	}

	protected void removeFromBadList(Node evNode) {
		ListIterator<Node> iter = badNodes.listIterator();
		
		while(iter.hasNext()) {
			Node n = iter.next();
			if(n == evNode) {
				iter.remove();
				return;
			}
		}
	}

	private void updateNodesRelIdx(double srcMovement, double maxDistanceToRun) {
		for(int i = 0; i < allNodes.length; ++i) {
			Node curr = allNodes[i];
			if(curr.state == State.Bad) {
				curr.relIdx += srcMovement;
			} else {// the node is good
				double relShift = Math.min(curr.relIdx, maxDistanceToRun- srcMovement);
				curr.relIdx = curr.relIdx - relShift; 
			}
		}
	}



}
